package converter;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Converter {
	private static NodeList layers = null;
	private static int tileSize;

	public static void main(String[] args) {
		String fileIn, fileOut;
		if(args.length>0) fileIn = args[0]; 
		else {
			System.out.println("Digite a localização do arquivo");
			Scanner scanner = new Scanner(System.in);
			fileIn = scanner.nextLine();
		}
		if(args.length>1) fileOut = args[1];
		else {
			System.out.println("Digite o destino do arquivo");
			Scanner scanner = new Scanner(System.in);
			fileOut = scanner.nextLine();
		}
		DocumentBuilderFactory docBuilderFac = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder docBuilder = docBuilderFac.newDocumentBuilder();
			File input =  new File(fileIn); 
			Document res = docBuilder.parse(input);
			Map map = new Map();
			decode(res.getDocumentElement(), map);
			
			File output = new File(fileOut);
			DataOutputStream file =  new DataOutputStream( new FileOutputStream(output)); 
			map.save(file);
			file.close();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void decode(Element documentElement, Map map) {
		tileSize = Integer.parseInt(documentElement.getAttribute("tilewidth"));  
		System.out.println("Map Tile Size: "+tileSize);
		
		String width = documentElement.getAttribute("width");
		map.setWidth(width);
		System.out.println("Map width: "+width);
		
		String height = documentElement.getAttribute("height");
		map.setHeigth(height);
		System.out.println("Map heigth: "+height);
		
		String tileset = getImageName(documentElement);
		map.setTileset(tileset);
		System.out.println("Map Tileset: "+tileset);
		
		System.out.println("#Bottom Layer#");
		map.setBottom(decodeLayer( readLayer(0, documentElement)));
		
		System.out.println("#Middle Layer#");
		map.setMiddle(decodeLayer( readLayer(1, documentElement)));
		
		System.out.println("#Top Layer#");
		map.setTop(decodeLayer( readLayer(2, documentElement)));
		
		System.out.println("#Objects Layer#");
		map.setObjects(decodeObjectGroup(documentElement));
		
		System.out.println("Leitura finalizada!");
	}

	private static Sprite[] decodeObjectGroup(Element documentElement) {
		Element objectGroup = (Element)(documentElement.getElementsByTagName("objectgroup").item(0));
		if(objectGroup==null) return new Sprite[0];
		NodeList objects = objectGroup.getElementsByTagName("object");
		int max = objects.getLength();
		Sprite []sprites = new Sprite[max];
		for(int i=0; i < max; ++i){
			System.out.println("Object:");
			sprites[i]=decodeObject((Element)objects.item(i));
		}
		return sprites;
	}

	private static Sprite decodeObject(Element object) {
		Sprite sprite = new Sprite();
		String name = object.getAttribute("name");
		System.out.println("  name: "+name);
		sprite.setName(name);
		
		String type = object.getAttribute("type");
		System.out.println("  type: "+ type);
		sprite.setType(type);
		 
		int posx = Integer.parseInt(object.getAttribute("x"))/tileSize;
		System.out.println("  posx: "+posx);
		sprite.setX(posx);
		
		int posy = Integer.parseInt(object.getAttribute("y"))/tileSize;
		System.out.println("  posy: "+posy);
		sprite.setY(posy);
		 
		int width = Integer.parseInt(object.getAttribute("width"))/tileSize;
		System.out.println("  width: "+width);
		sprite.setWidth(width);
		
		int height = Integer.parseInt(object.getAttribute("height"))/tileSize;
		System.out.println("  height: "+height);
		sprite.setHeight(height);
		
		NodeList properties = object.getElementsByTagName("properties");
		if(properties.getLength()>0){
			NodeList propertyGroup = ( (Element) properties.item(0)).getElementsByTagName("property");
			for(int i=0; i< propertyGroup.getLength(); ++i){
				Element property = (Element) propertyGroup.item(i);
				String pType = property.getAttribute("name");
				String pValue = property.getAttribute("value");
				System.out.println("  "+ pType+": "+pValue);
				sprite.addProperty(pType, pValue);
			}
		}
		
		
		return sprite;
	}

	private static long[] decodeLayer(Element layer) {
		long[] values = Base64Coder.decode2int( layer.getTextContent().trim());
		System.out.println("Contents: " + Arrays.toString(values));
		return values;
	}

	private static Element readLayer(int i, Element documentElement) {
		if (layers == null) {
			layers  = documentElement.getElementsByTagName("layer");
		}
		
		return (Element)layers.item(i);
	}

	private static String getImageName(Element documentElement) {
		Element image = (Element)(((Element) documentElement.getElementsByTagName("tileset").item(0)).getElementsByTagName("image").item(0));
		String imageName = image.getAttribute("source");
		int ind = imageName.lastIndexOf('/');
		if( ind != -1) imageName = imageName.substring(ind+1);
		return imageName;
	}
}
